package pub.developers.forum.app.manager;

import com.alibaba.fastjson.JSON;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import pub.developers.forum.api.model.PageRequestModel;
import pub.developers.forum.api.model.PageResponseModel;
import pub.developers.forum.api.request.AdminBooleanRequest;
import pub.developers.forum.api.request.user.*;
import pub.developers.forum.api.response.follow.commentFollowResponse;
import pub.developers.forum.api.response.follow.postsFollowResponse;
import pub.developers.forum.api.response.user.UserInfoResponse;
import pub.developers.forum.api.response.user.UserOptLogPageResponse;
import pub.developers.forum.api.response.user.UserPageResponse;
import pub.developers.forum.app.support.IsLogin;
import pub.developers.forum.app.support.LoginUserContext;
import pub.developers.forum.app.support.PageUtil;
import pub.developers.forum.app.support.Pair;
import pub.developers.forum.app.transfer.OptLogTransfer;
import pub.developers.forum.app.transfer.UserTransfer;
import pub.developers.forum.common.enums.CacheBizTypeEn;
import pub.developers.forum.common.enums.ErrorCodeEn;
import pub.developers.forum.common.enums.UserRoleEn;
import pub.developers.forum.common.enums.UserStateEn;
import pub.developers.forum.common.model.PageResult;
import pub.developers.forum.common.support.CheckUtil;
import pub.developers.forum.common.support.EventBus;
import pub.developers.forum.common.support.StringUtil;
import pub.developers.forum.domain.entity.*;
import pub.developers.forum.domain.repository.*;

import javax.annotation.Resource;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;


@Component
public class UserManager extends AbstractLoginManager {

    @Resource
    private OptLogRepository optLogRepository;

    @Resource
    private PostsRepository postsRepository;

    @Resource
    private UserFollowRepository userFollowRepository;

    @Resource
    private CommentRepository commentRepository;

    @Resource
    private UserRepository userRepository;

    /**
     * 邮箱 + 密码 登录
     * @param request
     * @return
     */
    public String emailRequestLogin(UserEmailLoginRequest request) throws Exception {
        // 判断邮箱是否存在
        User user = userRepository.getByEmail(request.getEmail());
        CheckUtil.isEmpty(user, ErrorCodeEn.USER_NOT_EXIST);
        CheckUtil.isTrue(UserStateEn.DISABLE.equals(user.getState()), ErrorCodeEn.USER_STATE_IS_DISABLE);

        // 判断登录密码是否正确
        CheckUtil.isFalse(StringUtil.md5UserPassword(request.getPassword()).equals(user.getPassword()), ErrorCodeEn.USER_LOGIN_PWD_ERROR);

        // 更新最后登录时间
        user.setLastLoginTime(new Date());
        userRepository.update(user);

        return login(user, request);
    }


    public String wxRequestLogin(String openid) throws Exception {
        // 判断openid是否存在
        User user = userRepository.getByOpenid(openid);
        // 如果不存在，注册
       if (user == null) {
           UserRegisterRequest request = new UserRegisterRequest();
           request.setOpenid(openid);
           request.setNickname("微信用户");
           request.setPassword("1234");
           user = UserTransfer.toUser(request);

           userRepository.save(user);

           // 触发保存操作日志事件
           EventBus.emit(EventBus.Topic.USER_REGISTER,user);
       }else {
           // 更新最后登陆时间
           user.setLastLoginTime(new Date());
           userRepository.update(user);
       }

        return login(user,new UserBaseLoginRequest());
    }

    public String wxRequestLogin(UserWxLoginRequest request) throws Exception {
        // 判断openid是否存在
        User user = userRepository.getByOpenid(request.getOpenid());


        if (user == null) {    //如果不存在,注册
            UserRegisterRequest tmp = new UserRegisterRequest();
            tmp.setOpenid(request.getOpenid());
            tmp.setNickname(RandomStringUtils.randomAlphanumeric(8)); //随机生成一个昵称
            if (request.getAvatar() != null &&!request.getAvatar().isEmpty()){
                tmp.setAvatar(request.getAvatar());
            }
            if ( request.getNickname() != null && !request.getNickname().isEmpty()){
                tmp.setNickname(request.getNickname());
            }
            user = UserTransfer.toUser(tmp);

            userRepository.save(user);
        }else {// 登录
            CheckUtil.isTrue(UserStateEn.DISABLE.equals(user.getState()), ErrorCodeEn.USER_STATE_IS_DISABLE);
            // 更新最后登陆时间
            user.setLastLoginTime(new Date());
            userRepository.update(user);
        }


        return login(user,request);
    }

    @IsLogin(role = UserRoleEn.ADMIN)
    public PageResponseModel<UserOptLogPageResponse> pageOptLog(PageRequestModel<UserOptLogPageRequest> pageRequestModel) {
        PageResult<OptLog> pageResult = optLogRepository.page(PageUtil.buildPageRequest(pageRequestModel, OptLogTransfer.toOptLog(pageRequestModel.getFilter())));

        if (ObjectUtils.isEmpty(pageResult.getList())) {
            return PageUtil.buildPageResponseModel(pageResult, new ArrayList<>());
        }
        List<Long> userIdList = pageResult.getList().stream().map(OptLog::getOperatorId).collect(Collectors.toList());
        List<User> userList = userRepository.queryByIds(userIdList);

        return PageUtil.buildPageResponseModel(pageResult, UserTransfer.toUserOptLogPageResponses(pageResult.getList(), userList));
    }

    @IsLogin(role = UserRoleEn.ADMIN)
    public void enable(Long uid) {
        User user = userRepository.get(uid);
        CheckUtil.isEmpty(user, ErrorCodeEn.USER_NOT_EXIST);

        user.setState(UserStateEn.ENABLE);
        userRepository.update(user);
    }

    @IsLogin(role = UserRoleEn.ADMIN)
    public void disable(Long uid) {
        User user = userRepository.get(uid);
        CheckUtil.isEmpty(user, ErrorCodeEn.USER_NOT_EXIST);
        CheckUtil.isEmpty(UserRoleEn.SUPER_ADMIN.equals(user.getRole()), ErrorCodeEn.COMMON_TOKEN_NO_PERMISSION);

        user.setState(UserStateEn.DISABLE);
        userRepository.update(user);

        // 删除用户登录信息
        deleteLoginUser(uid);
    }

    @IsLogin
    public void follow(Long followed) throws Exception {
        Long follower = LoginUserContext.getUser().getId();
        userRepository.follow(followed, follower);

        Pair<Long> follow = Pair.build(followed, follower);
        EventBus.emit(EventBus.Topic.USER_FOLLOW, follow);
    }

    @IsLogin
    public void cancelFollow(Long followed) throws Exception {
        Follow follow = userRepository.getFollow(followed, LoginUserContext.getUser().getId());
        if (follow == null) {
            return;
        }
        userRepository.cancelFollow(follow.getId());

        EventBus.emit(EventBus.Topic.USER_CANCEL_FOLLOW, follow);
    }

    /**
     * 获取 token 对应用户详情
     * @param token
     * @return
     */
    public UserInfoResponse info(String token) {
        String cacheUserStr = cacheService.get(CacheBizTypeEn.USER_LOGIN_TOKEN, token);
        CheckUtil.isEmpty(cacheUserStr, ErrorCodeEn.USER_TOKEN_INVALID);

        return UserTransfer.toUserInfoResponse(JSON.parseObject(cacheUserStr, User.class));
    }

    public UserInfoResponse info(Long uid) {
        User user = userRepository.get(uid);
        CheckUtil.isEmpty(user, ErrorCodeEn.USER_NOT_EXIST);

        return UserTransfer.toUserInfoResponse(user);
    }

    /**
     * 用户注册
     * @param request
     */
    @Transactional
    public String register(UserRegisterRequest request) throws Exception {
        // 判断邮箱是否已经被注册
        User user = userRepository.getByEmail(request.getEmail());
        CheckUtil.isNotEmpty(user, ErrorCodeEn.USER_REGISTER_EMAIL_IS_EXIST);

        User registerUser = UserTransfer.toUser(request);

        // 保存注册用户
        userRepository.save(registerUser);

        // 触发保存操作日志事件
        EventBus.emit(EventBus.Topic.USER_REGISTER, registerUser);

        return login(registerUser, request);
    }

    /**
     * 登出
     * @param request
     */
    public void logout(UserTokenLogoutRequest request) throws Exception {
        User user = delCacheLoginUser(request.getToken());
        if (ObjectUtils.isEmpty(user)) {
            return;
        }

        // 触发保存操作日志事件
        EventBus.emit(EventBus.Topic.USER_LOGOUT, OptLog.createUserLogoutRecordLog(user.getId(), JSON.toJSONString(request)));
    }

    // 注销
    @IsLogin
    public void signOut() {
        User user = LoginUserContext.getUser();

        // 删除帖子
        postsRepository.deleteByAuthorId(user.getId());
        // 删除评论
        commentRepository.deleteByUserId(user.getId());
        // 删除用户
        userRepository.delete(user.getId());

    }

    /**
     * 用户更新基本信息
     * @param request
     */
    @IsLogin
    @Transactional
    public void updateInfo(UserUpdateInfoRequest request) {
        User loginUser = LoginUserContext.getUser();

        User user = userRepository.getByEmail(request.getEmail());
        if (!ObjectUtils.isEmpty(user)) {
            CheckUtil.isFalse(user.getId().equals(loginUser.getId()), ErrorCodeEn.USER_REGISTER_EMAIL_IS_EXIST);
        }

        User updateUser = UserTransfer.toUser(loginUser, request);

        // 更新缓存中登录用户信息
        updateCacheUser(updateUser);
        userRepository.update(updateUser);
    }


    /**
     * 用户更新头
     * @param linkFilenameData
     */
    @IsLogin
    @Transactional
    public void updateHeadimg(String linkFilenameData) {
        User loginUser = LoginUserContext.getUser();

       /* User user = userRepository.getByEmail(request.getEmail());
        if (!ObjectUtils.isEmpty(user)) {
            CheckUtil.isFalse(user.getId().equals(loginUser.getId()), ErrorCodeEn.USER_REGISTER_EMAIL_IS_EXIST);
        }*/
        loginUser.setAvatar(linkFilenameData);
        // 更新缓存中登录用户信息
        updateCacheUser(loginUser);
        userRepository.update(loginUser);
    }
    /**
     * 更新登录密码
     * @param request
     */
    @IsLogin
    @Transactional
    public void updatePwd(UserUpdatePwdRequest request) {
        User user = LoginUserContext.getUser();
        CheckUtil.isFalse(StringUtil.md5UserPassword(request.getOldPassword()).equals(user.getPassword()), ErrorCodeEn.USER_OLD_PASSWORD_ERROR);

        user.setPassword(StringUtil.md5UserPassword(request.getNewPassword()));

        // 更新缓存中登录用户信息
        updateCacheUser(user);
        userRepository.update(user);
    }

    @IsLogin(role = UserRoleEn.ADMIN)
    public PageResponseModel<UserPageResponse> page(PageRequestModel<UserAdminPageRequest> pageRequestModel) {
        PageResult<User> pageResult = userRepository.page(PageUtil.buildPageRequest(pageRequestModel, UserTransfer.toUser(pageRequestModel.getFilter())));

        return PageUtil.buildPageResponseModel(pageResult, UserTransfer.toUserPageResponses(pageResult.getList()));
    }

    public PageResponseModel<UserPageResponse> pageFollower(PageRequestModel<Long> pageRequestModel) {
        PageResult<User> pageResult = userRepository.pageFollower(PageUtil.buildPageRequest(pageRequestModel, pageRequestModel.getFilter()));

        return PageUtil.buildPageResponseModel(pageResult, UserTransfer.toUserPageResponses(pageResult.getList()));
    }

    public PageResponseModel<UserPageResponse> pageFans(PageRequestModel<Long> pageRequestModel) {
        PageResult<User> pageResult = userRepository.pageFans(PageUtil.buildPageRequest(pageRequestModel, pageRequestModel.getFilter()));

        return PageUtil.buildPageResponseModel(pageResult, UserTransfer.toUserPageResponses(pageResult.getList()));
    }

    @IsLogin
    public Boolean hasFollow(Long followed) {
        Follow follow = userRepository.getFollow(followed, LoginUserContext.getUser().getId());
        return follow != null;
    }

    public PageResponseModel<UserPageResponse> pageActive(PageRequestModel pageRequestModel) {
        PageResult<User> pageResult = userRepository.pageActive(PageUtil.buildPageRequest(pageRequestModel));

        return PageUtil.buildPageResponseModel(pageResult, UserTransfer.toUserPageResponses(pageResult.getList()));
    }

    private void updateCacheUser(User updateUser) {
        LoginUserContext.setUser(updateUser);
        cacheLoginUser(LoginUserContext.getToken(), updateUser);
    }

    private User delCacheLoginUser(String token) {
        String oldUser = cacheService.get(CacheBizTypeEn.USER_LOGIN_TOKEN, token);
        if (ObjectUtils.isEmpty(oldUser)) {
            return null;
        }

        User loginUser = JSON.parseObject(oldUser, User.class);
        cacheService.del(CacheBizTypeEn.USER_LOGIN_TOKEN, String.valueOf(loginUser.getId()));
        cacheService.del(CacheBizTypeEn.USER_LOGIN_TOKEN, token);

        return loginUser;
    }


    @IsLogin(role = UserRoleEn.SUPER_ADMIN)
    public void updateRole(AdminBooleanRequest booleanRequest) {
        User user = userRepository.get(booleanRequest.getId());
        CheckUtil.isEmpty(user, ErrorCodeEn.USER_NOT_EXIST);

        user.setRole(booleanRequest.getIs() ? UserRoleEn.ADMIN : UserRoleEn.USER);
        userRepository.update(user);
    }

    //获取用户的粉丝列表
    @IsLogin
    public List<UserInfoResponse> querySelfFans()
    {
        //拿到当前登录用户的id
        User loginUser = LoginUserContext.getUser();
        Long id = loginUser.getId();//当前登录用户的id
        return userRepository.querySelfFans(id);
    }

    // 获取用户的关注列表
    @IsLogin
    public PageResponseModel<UserInfoResponse> querySelfFollower(Object userId , Integer pageSize , Integer pageNo){
        if (userId == null || new Long(String.valueOf(userId)) == 0){
            userId = LoginUserContext.getUser().getId();
        }
        System.out.println(userId);
        PageResult<UserInfoResponse>  pageResult = userRepository.queryMyLove(userId , pageSize , pageNo);
        return PageResponseModel.build(pageResult.getTotal(), pageResult.getSize() , pageResult.getList());
    }

    //获取用户的点赞信息 帖子
    @IsLogin
    public List<postsFollowResponse> queryFollowContent()
    {
        List<postsFollowResponse> result = new ArrayList<>();
        //根据当前登录的用户的id , 拿到该用户发表的帖子id
        Long id = LoginUserContext.getUser().getId();
        Long[] postIds = postsRepository.getPostsId(id); // 28 29 30 32 33 用户发表的帖子的id

        //根据拿到的帖子id 查看 谁给我点了赞   //循环遍历 , 做好一一对应
        for (Long postId : postIds)
        {
            Long[] followersId = userFollowRepository.getFollowersIds(postId);
            //如果有人给帖子点赞
            //根据点赞的人的id 拿到点赞的人的昵称以及头像
            for (Long followerId : followersId)
            {
                //根据帖子id 拿到帖子信息
                BasePosts postInformation = postsRepository.getPostInformation(postId);
                //根据点赞者的id 拿到点赞的人的信息
                UserInfoResponse followerInformation = userRepository.getUserInformation(followerId);

                postsFollowResponse postsFollow = new postsFollowResponse(); // 创建一个新的对象

                postsFollow.setId(postId); // 帖子id
                postsFollow.setCreateAt(postInformation.getCreateAt()); // 帖子发表时间
                postsFollow.setTitle(postInformation.getTitle()); // 帖子标题
                postsFollow.setMarkdownContent(postInformation.getMarkdownContent()); // 帖子文本内容
                postsFollow.setHtmlContent(postInformation.getHtmlContent()); // 帖子html内容
                postsFollow.setViews(postInformation.getViews()); // 帖子浏览量
                // 使用构建器模式创建 follower 对象并为其属性赋值
                postsFollowResponse.follower follower = postsFollowResponse.follower.builder()
                        .id(followerInformation.getId())
                        .nickname(followerInformation.getNickname())
                        .avatar(followerInformation.getAvatar())
                        .build();
                postsFollow.setFollower(follower); // 将 follower 对象设置到 postsFollow 对象中
                result.add(postsFollow); // 将 postsFollow 对象添加到结果集合中
            }
        }
        return result;
    }

    //获取给评论点赞的消息
    @IsLogin
    public List<commentFollowResponse> queryFollowCommentListManager()
    {
        List<commentFollowResponse> result = new ArrayList<>();
        //拿到当前登录的用户id
        Long id = LoginUserContext.getUser().getId();
        //根据当前登录的用户id , 拿到用户被点赞的评论
        Long[] commentsId = commentRepository.getCommentIdByUserid(id);
        //////System.out.println("该用户发表的评论的id:"+ Arrays.toString(commentsId));
        //根据评论id , 查看谁给我的评论点了赞 循环遍历
        for (Long commentId : commentsId)
        {
            Long[] followers = commentRepository.getAllFollower(commentId); //给我评论点赞的用户的id
//            //////System.out.println(Arrays.toString(followers));
            for (Long follower : followers)
            {
                //根据评论id 拿到评论内容
                Comment comment = commentRepository.get(commentId);
                //////System.out.println("被点赞的评论的内容"+comment);
                //根据用户id , 拿到用户信息
                UserInfoResponse userInformation = userRepository.getUserInformation(follower);
                //////System.out.println("给我评论点赞的用户的信息:"+userInformation);
                commentFollowResponse response = commentFollowResponse.builder()
                        .id(commentId) //评论id
                        .createAt(comment.getCreateAt()) //评论发表日期
                        .postsId(comment.getPostsId()) // 评论所属的帖子的id
                        .content(comment.getContent()) // 评论的内容
                        .followCount(comment.getFollowCount()) // 评论被点赞的次数
                        .build();

                commentFollowResponse.follower followerObject = commentFollowResponse.follower.builder()
                        .id(follower)
                        .nickname(userInformation.getNickname())
                        .avatar(userInformation.getAvatar())
                        .build();

                response.setFollower(followerObject);
                result.add(response);
            }
        }
        return result;
    }

    //将用户邮件中的验证码存入redis中
    public void saveEmailCode(String email , String code)
    {
        userRepository.saveCode(email , code);
    }

    //用户验证码登录
    public String emailCodeLoginManager(UserRegisterRequest userRegisterRequest) throws Exception {
        String email = userRegisterRequest.getEmail();
        String inputCode = userRegisterRequest.getCode();
        //从redis库中取出验证码
        String rightCode = userRepository.rightCode(email);
        //如果redis数据库中的验证码与用户输入的相等
        if (inputCode.equals(rightCode))
        {
           //判断邮箱是否被注册
            User user = userRepository.getByEmail(email);
            if (user == null)
            {
                int minLength = 8;
                int maxLength = 12;
                int length = minLength + random.nextInt(maxLength - minLength + 1);
                String randomString = generateRandomString(length);
                //如果用户不存在注册 设置一些默认信息
                UserRegisterRequest request = new UserRegisterRequest();
                request.setNickname(randomString);
                request.setEmail(email);
                request.setPassword("1234");
                request.setAvatar("https://cdn.jiuzhimcu.com/avatar/avatar.jpg");
                user = UserTransfer.toUser(request);
                userRepository.save(user); //保存注册用户
                //触发日志保存时间
                EventBus.emit(EventBus.Topic.USER_REGISTER , user);
            }
            else
            {
                //更新最后登录时间
                user.setLastLoginTime(new Date());
                userRepository.update(user);
                return login(user , userRegisterRequest);
            }
            return login(user , userRegisterRequest);
        }
        return "error";
    }

    //用户查看自己的个人信息或者其它人的信息
    @IsLogin
    public UserInfoResponse querySelfInformationManager(Long userId)
    {
        //拿到当前登录用户的id
        if (userId == null){
            userId = LoginUserContext.getUser().getId();
        }
        //根据当前登录用户的id 查找其个人信息
        User selfInformation = userRepository.selfInformation(userId);
        return UserTransfer.toUserInfoResponse(selfInformation);
    }

    //查询用户上传的图片的数量
    @IsLogin
    public boolean queryImgCount()
    {
        //拿到当前登录用户的id
        Long id = LoginUserContext.getUser().getId();
        //根据当前登录用户的id 查找其个人信息
        User selfInformation = userRepository.selfInformation(id);
        String avatars = selfInformation.getAvatar();
        String[] avatarArr = avatars.split(" ");
        return avatarArr.length < 6;
    }

    //s2cyx3wmf.hn-bkt.clouddn.com\1号.png s2cyx3wmf.hn-bkt.clouddn.com\2号.png s2cyx3wmf.hn-bkt.clouddn.com\3号.png s2cyx3wmf.hn-bkt.clouddn.com\4号.png
    //用户上传头像功能3
    @IsLogin
    public String updateAvatar3(String avatar)
    {
        User loginUser = LoginUserContext.getUser();
        //拿到当前登录用户的id 拿到用户的头像列表
        Long id = loginUser.getId();
        User selfInformation = userRepository.selfInformation(id);
        String avatars = selfInformation.getAvatar();
        String newAvatars = "";
        if (avatars.isEmpty())
        {
            newAvatars = avatar;
        }
        else
        {
            newAvatars = avatars + " " + avatar;
        }
        loginUser.setAvatar(newAvatars);
        //更新用户信息
        updateCacheUser(loginUser);
        userRepository.update(loginUser);
        return newAvatars;
    }

    //用户删除图片
    @IsLogin
    public void deleteAvatar(String deleteAvatarName)
    {
        //////System.out.println("delete:"+deleteAvatarName);
        User loginUser = LoginUserContext.getUser();
        //拿到当前登录用户的id 拿到用户的头像列表
        Long id = loginUser.getId();
        User selfInformation = userRepository.selfInformation(id);
        String avatars = selfInformation.getAvatar();
        String newAvatars = avatars.replace(deleteAvatarName , "").trim();
        loginUser.setAvatar(newAvatars);
        //更新用户信息
        updateCacheUser(loginUser);
        userRepository.update(loginUser);
    }

    //拿到当前登录用户的openid
    @IsLogin
    public String getOpenId()
    {
        Long id = LoginUserContext.getUser().getId();
        return userRepository.queryOpenId(id);
    }

    //查询当前登录用户上传的头像是否用重复
    public Boolean getSameAvatar(String avatar)
    {
        User loginUser = LoginUserContext.getUser();
        //拿到当前登录用户的id 拿到用户的头像列表
        Long id = loginUser.getId();
        User selfInformation = userRepository.selfInformation(id);
        String avatars = selfInformation.getAvatar();
        return avatars.contains(avatar);
    }

    // 生成8-12位随机字符串
    private static final String CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
    private static SecureRandom random = new SecureRandom();

    public static String generateRandomString(int length) {
        StringBuilder sb = new StringBuilder(length);
        for (int i = 0; i < length; i++) {
            sb.append(CHARACTERS.charAt(random.nextInt(CHARACTERS.length())));
        }
        return sb.toString();
    }


    //删除用户
    @IsLogin(role = UserRoleEn.ADMIN)
    public void deleteUserManager(Long id)
    {
        userRepository.delete(id);
    }

}


